using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.Model.Enums;
using AiQiuQuan.Sport.Model.Models;
using AiQiuQuan.Sport.WebApi.Core;
using AiQiuQuan.Sport.WebApi.Entities;
using AiQiuQuan.Sport.WebApi.Repositories;
using DotNetCore.CAP;
using RedLockNet;
using MapsterMapper;
using Microsoft.EntityFrameworkCore;

namespace AiQiuQuan.Sport.WebApi.Services.Impl
{
    /// <summary>
    /// 场馆数据管理
    /// </summary>
    public partial class VenueService : IVenueService
    {
        private readonly ICapPublisher _capPublisher;
        private readonly IMapper _mapper;
        private readonly ICurrentInfo _currentInfo;
        private readonly IVenueWithdrawRepository _venueWithdrawRepository;
        private readonly IFrameworkUsersRepository _frameworkUsersRepository;
        private readonly IBaseUserRepository _baseUserRepository;
        private readonly IVenueInfoRepository _venueInfoRepository;
        private readonly ISiteInfoRepository _siteInfoRepository;
        private readonly ICoacherVenueRepository _coacherVenueRepository;
        private readonly ISitePriceSpecialRuleRepository _sitePriceSpecialRuleRepository;
        private readonly IVenueInfoRefundRuleConfigRepository _venueInfoRefundRuleConfigRepository;
        private readonly IBusinessHoursConfigRepository _buinessHoursConfigRepository;
        private readonly ISpecialDateSettingRepository _specialDateSettingRepository;
        private readonly ISitePriceListRepository _priceListRepository;
        private readonly IFrameworkUserRolesRepository _userRoleRepository;
        private readonly IDistributedLockFactory _distributedLockFactory;

        /// <summary>
        /// ctor
        /// </summary>
        public VenueService(
            IMapper mapper,
            ICurrentInfo currentInfo,
            ICapPublisher capPublisher,
            IVenueWithdrawRepository venueWithdrawRepository,
            IFrameworkUsersRepository frameworkUsersRepository,
            IBaseUserRepository baseUserRepository,
            IVenueInfoRepository venueInfoRepository,
            ISiteInfoRepository siteInfoRepository,
            ICoacherVenueRepository coacherVenueRepository,
            ISitePriceSpecialRuleRepository sitePriceSpecialRuleRepository,
            IVenueInfoRefundRuleConfigRepository venueInfoRefundRuleConfigRepository,
            IBusinessHoursConfigRepository buinessHoursConfigRepository,
            ISpecialDateSettingRepository specialDateSettingRepository,
            ISitePriceListRepository priceListRepository,
            IFrameworkUserRolesRepository userRoleRepository,
            IDistributedLockFactory distributedLockFactory)
        {
            _mapper = mapper;
            _currentInfo = currentInfo;
            _capPublisher = capPublisher;
            _venueWithdrawRepository = venueWithdrawRepository;
            _frameworkUsersRepository = frameworkUsersRepository;
            _baseUserRepository = baseUserRepository;
            _venueInfoRepository = venueInfoRepository;
            _siteInfoRepository = siteInfoRepository;
            _coacherVenueRepository = coacherVenueRepository;
            _sitePriceSpecialRuleRepository = sitePriceSpecialRuleRepository;
            _venueInfoRefundRuleConfigRepository = venueInfoRefundRuleConfigRepository;
            _buinessHoursConfigRepository = buinessHoursConfigRepository;
            _specialDateSettingRepository = specialDateSettingRepository;
            _priceListRepository = priceListRepository;
            _userRoleRepository = userRoleRepository;
            _distributedLockFactory = distributedLockFactory;
        }

        /// <summary>
        /// 审核提现
        /// </summary>
        public async Task<UnaryResult> AuditWithdrawAsync(VenueAuditWithdrawRequestDto request)
        {
            await using (var redlock = await _distributedLockFactory.CreateLockAsync(request.WithdrawId.ToString(), TimeSpan.FromSeconds(20)))
            {
                if (!redlock.IsAcquired)
                {
                    return UnaryResult.Faild(10, "提现处理中，请稍后");
                }

                var withdraw = await _venueWithdrawRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == request.WithdrawId);
                var platformUser = await _frameworkUsersRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == request.PlatformUserId);
                var unaryResult = await ValidWithdrawAsync(withdraw, platformUser, request);
                if (unaryResult.Code != 0)
                {
                    return unaryResult;
                }

                withdraw.VW_State = request.State;
                withdraw.FrameworkUserID = request.PlatformUserId;
                withdraw.VW_Reviewer = platformUser.Name;
                withdraw.VW_ReviewTime = DateTimeOffset.Now;
                withdraw.VW_RejectReason = request.State == WithdrawStateEnum.Rejected ? request.Remark : null;
                withdraw.TotalBalance = request.State == WithdrawStateEnum.Approved ? withdraw.TotalBalance - withdraw.VW_Total : withdraw.TotalBalance;

                //场馆记录列表
                var list = new List<VenueInfoAccountDetailAddDto>();
                if (request.State == WithdrawStateEnum.Rejected)
                {
                    //拒绝后，直接处理场馆账户相关事务
                    list.Add(new VenueInfoAccountDetailAddDto
                    {
                        VenueID = withdraw.VenueInfoID.Value,
                        Amount = withdraw.VW_Total.GetValueOrDefault(),
                        OperateType = VenueAccountOperateEnum.UnFrozen,
                        SourceType = VenueAccountSourceEnum.Withdraw,
                        Remark = $"提现单:{withdraw.VW_Code}审核拒绝，金额不变"
                    });
                }
                else
                {
                    ////第三方转账成功
                    //var transferModel = new TransferAccountAddDto
                    //{
                    //    BusinessId = withdraw.ID,
                    //    BusinessType = BusinessTypeEnum.VenueSite,
                    //    AccountId = user.U_WxOpenId,
                    //    AccountName = user.CardName,
                    //    UserId = user.ID,
                    //    Amount = withdraw.VW_Total.GetValueOrDefault(),
                    //    ServiceChargeAmount = withdraw.VW_ServicePrice.GetValueOrDefault(),
                    //    Remark = $"场馆提现,申请人code:{user.U_Code}"
                    //};
                    //var unaryResult = await _transferAccountService.WxTransferToWalletAsync(transferModel);
                    //if (unaryResult.Code != 0)
                    //{
                    //    return unaryResult;
                    //}

                    //场馆账户记录
                    list.Add(new VenueInfoAccountDetailAddDto
                    {
                        VenueID = withdraw.VenueInfoID.Value,
                        Amount = withdraw.VW_Total.GetValueOrDefault(),
                        OperateType = VenueAccountOperateEnum.Reduce,
                        SourceType = VenueAccountSourceEnum.Withdraw,
                        Remark = $"提现单:{withdraw.VW_Code}审核通过，打款金额:{withdraw.VW_Total}"
                    });
                    if (withdraw.VW_ServicePrice > 0)
                    {
                        list.Add(new VenueInfoAccountDetailAddDto
                        {
                            VenueID = withdraw.VenueInfoID.Value,
                            Amount = withdraw.VW_ServicePrice.GetValueOrDefault(),
                            OperateType = VenueAccountOperateEnum.Reduce,
                            SourceType = VenueAccountSourceEnum.Withdraw,
                            Remark = $"提现单:{withdraw.VW_Code}审核通过，服务费金额:{withdraw.VW_ServicePrice}"
                        });
                    }
                }

                await _venueWithdrawRepository.UpdateAsync(withdraw);
                //处理场馆账户及记录
                if (list.Any())
                {
                    await _capPublisher.PublishAsync(MessageTopic.VENUE_ACCOUNT_DETAIL_ADD, list);
                }
            }

            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 分页请求
        /// </summary>
        public async Task<PageResult<VenueInfoDto>> PageListAsync(VenuePageRequestDto request)
        {
            var queryable = GeneratePageListQueryable(request);
            var pagelist = await queryable.OrderBy(m => m.CreateTime).PageListAsync<VenueInfo, VenueInfoDto>(request, _mapper);
            return pagelist;
        }

        /// <summary>
        /// 查询
        /// </summary>
        public async Task<VenueInfoDto> GetAsync(Guid id)
        {
            var entiy = await _venueInfoRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == id);
            return _mapper.Map<VenueInfoDto>(entiy);
        }

        /// <summary>
        /// 教练场馆分页
        /// </summary>
        public async Task<PageResult<VenueInfoDto>> PageListCoacherAsync(VenuePageRequestDto request)
        {
            var queryable = GeneratePageListCoacherQueryable(request);
            var pagelist = await queryable.OrderBy(m => m.CreateTime).PageListAsync<VenueInfo, VenueInfoDto>(request, _mapper);
            return pagelist;
        }

        /// <summary>
        /// 场馆教练更新
        /// </summary>
        public async Task<UnaryResult> UpdateVenueCoacherAsync(VenueCoacherUpdateDto request)
        {
            var builder = await _coacherVenueRepository.UpdatePartialAsync();
            await builder.Set(m => m.IsRecommend, request.IsRecommend)
                .Where(m => m.VenueId == request.VenueId && m.CoacherUserId == request.CoacherUserId)
                .ExecuteAsync();
            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场地列表
        /// </summary>
        /// <param name="venueId">场馆ID</param>
        /// <returns></returns>
        public async Task<List<SiteInfoDto>> GetVenueSiteListAsync(Guid venueId)
        {
            var list = await _siteInfoRepository.AsNoTracking()
                .Where(m => m.VenueInfoID == venueId).Select(m => _mapper.Map<SiteInfoDto>(m)).ToListAsync();
            return list;
        }

        /// <summary>
        /// 场地分页列表
        /// </summary>
        public async Task<PageResult<SiteInfoDto>> GetVenueSitePageListAsync(VenueSitePageRequestDto request)
        {
            var queryable = GenerateSitePageListQueryable(request);
            var pagelist = await queryable.OrderBy(m => m.CreateTime).PageListAsync(request);
            return pagelist;
        }

        /// <summary>
        /// 场地状态更新
        /// </summary>
        public async Task<UnaryResult> UpdateSiteStateAsync(VenueSiteStateUpdateDto request)
        {
            var builder = await _siteInfoRepository.UpdatePartialAsync();
            await builder.Set(m => m.SiteState, request.State).Where(m => m.ID == request.SiteId).ExecuteAsync();
            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场地特殊规则分页列表
        /// </summary>
        public async Task<PageResult<SitePriceSpecialRuleDto>> GetVenueSiteSpecialRulePageListAsync(VenueSitePageRequestDto request)
        {
            var queryable = GenerateSiteSpecialRulePageListQueryable(request);
            var pagelist = await queryable.OrderBy(m => m.CreateTime).PageListAsync(request);
            return pagelist;
        }

        /// <summary>
        /// 场馆退款规则分页列表
        /// </summary>
        public async Task<PageResult<VenueInfoRefundRuleSimpleDto>> GetVenueRefundRulePageListAsync(VenuePageRequestDto request)
        {
            var list = new List<VenueInfoRefundRuleSimpleDto>();
            var queryable = GenerateRefundRuleVenuePageListQueryable(request);
            var pageResult = await queryable.Select(m => new VenueInfoRefundRuleSimpleDto { VenueInfoID = m.ID, VenueName = m.VI_Name, CreateTime = m.CreateTime })
                .OrderBy(m => m.CreateTime).PageListAsync(request);
            foreach (var item in pageResult.Result)
            {
                var refundRuleList = await GenerateRefundRuleListQueryable(item.VenueInfoID).ToListAsync();
                item.Condtion1 = refundRuleList[0];
                if (refundRuleList.Count >= 2)
                {
                    item.Condtion2 = refundRuleList[1];
                }

                if (refundRuleList.Count >= 3)
                {
                    item.Condtion3 = refundRuleList[2];
                }

                item.Condtion4 = refundRuleList[refundRuleList.Count - 1];
                item.Condtion4.VIRRC_RefundRatio = 0;
            }

            return pageResult;
        }

        /// <summary>
        /// 场馆退款规则列表
        /// </summary>
        /// <param name="venueId">场馆ID</param>
        /// <returns></returns>
        public async Task<List<VenueInfoRefundRuleConfigDto>> GetVenueRefundRuleListAsync(Guid venueId)
        {
            var queryable = GenerateRefundRuleListQueryable(venueId);
            var sql = queryable.ToQueryString();
            return await queryable.ToListAsync();
        }

        /// <summary>
        /// 场地价格特殊规则列表
        /// </summary>
        /// <param name="siteId">地址ID</param>
        public async Task<List<SitePriceSpecialRuleDto>> GetPriceSpecialRuleListAsync(Guid siteId)
        {
            var queryable = GenerateSiteSpecialRuleListQueryable(siteId);
            var list = await queryable.ToListAsync();
            return list;
        }

        /// <summary>
        /// 场地价格特殊规则增加
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<UnaryResult> AddSiteSpecialRuleAsync(SitePriceSpecialRuleAddDto request)
        {
            var site = await _siteInfoRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == request.SiteInfoID);
            if (site == null)
            {
                return UnaryResult.Faild(10, "场地不存在");
            }

            var entity = _mapper.Map<SitePriceSpecialRule>(request);
            entity.VenueInfoID = site.VenueInfoID;
            entity.SPSR_IsEffect = true;
            await _sitePriceSpecialRuleRepository.AddAsync(entity);
            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场地价格特殊规则更新
        /// </summary>
        public async Task<UnaryResult> UpdateSiteSpecialRuleAsync(SitePriceSpecialRuleUpdateDto request)
        {
            var special = await _sitePriceSpecialRuleRepository.FirstOrDefaultAsync(m => m.ID == request.ID);
            if (special == null)
            {
                return UnaryResult.Faild(10, "场地价格特殊规则不存在");
            }

            _mapper.Map(request, special);
            await _sitePriceSpecialRuleRepository.UpdateAsync(special);
            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场地价格特殊规则状态更新
        /// </summary>
        public async Task<UnaryResult> UpdateSiteSpecialRuleStateAsync(SitePriceSpecialRuleStateUpdateDto request)
        {
            var builder = await _sitePriceSpecialRuleRepository.UpdatePartialAsync();
            await builder.Set(m => m.SPSR_IsEffect, request.SPSR_IsEffect).Where(m => m.ID == request.ID).ExecuteAsync();

            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场地价格特殊规则删除
        /// </summary>
        /// <param name="siteSpecialRuleID">场地价格特殊规则ID</param>
        public async Task<UnaryResult> DeleteSiteSpecialRuleAsync(Guid siteSpecialRuleID)
        {
            await _sitePriceSpecialRuleRepository.DeleteAsync(m => m.ID == siteSpecialRuleID);
            return UnaryResult.Succeed();
        }

        /// <summary>
        /// 场馆场地价格列表
        /// </summary>
        public async Task<SitePriceSimpleDto> GetSitePriceSimpleInfoAsync(SitePriceSimpleRequestDto request)
        {
            var result = new SitePriceSimpleDto();
            if (request.QueryDate.Date < DateTimeOffset.Now.Date)
            {
                return result;
            }

            //获取场馆下的场地列表
            var siteStateList = new List<SiteStateEnum> { SiteStateEnum.Normal, SiteStateEnum.Repair };
            var siteList = await _siteInfoRepository.AsNoTracking().Where(m => m.VenueInfoID == request.VenueId && siteStateList.Contains(m.SiteState)).ToListAsync();
            if (!siteList.Any())
            {
                return result;
            }

            //当前时间是否是工作日
            //1.按常规看是否是工作日
            //2.当前时间是否设置的有特殊日子
            var specialSetting = await _specialDateSettingRepository.AsNoTracking().FirstOrDefaultAsync(m => m.VenueInfoID == request.VenueId && m.Dates == request.QueryDate.Date);
            var IsWork = specialSetting == null ? Tool.IsWorkDay(request.QueryDate.DateTime) : specialSetting.IsWorkDate;
            //根据工作日休息日查找最大营业时间列表
            var siteIdList = siteList.Select(m => m.ID).ToList();
            var businessHoursConfigList = await GetMaxBusinessHourConfigListAsync(siteIdList, IsWork.Value);
            if (!businessHoursConfigList.Any())
            {
                return result;
            }

            foreach (var item in businessHoursConfigList)
            {
                result.TimeList.Add(new SitePriceSimpleDto.TimeInfo { StartTime = item.TimeSlotBegin, EndTime = item.TimeSlotEnd });
            }

            foreach (var site in siteList)
            {
                SitePriceList sitePrice = null;
                var priceSimple = new SitePriceSimpleDto.SiteSimpleDto { ID = site.ID, Name = site.SiteName };
                result.SiteList.Add(priceSimple);
                foreach (var item in businessHoursConfigList)
                {
                    sitePrice = await _priceListRepository.AsNoTracking().FirstOrDefaultAsync(m => m.SiteInfoID == site.ID && m.SPL_Date.Date == request.QueryDate.Date
                   && m.SPL_TimeSlot == item.TimeSlotBegin && m.SPL_TimeSlotEnd == item.TimeSlotEnd);
                    var priceDto = new SitePriceDto
                    {
                        VenueInfoID = site.VenueInfoID,
                        SiteInfoID = site.ID,
                        SPL_TimeSlot = item.TimeSlotBegin,
                        SPL_Date = request.QueryDate.Date,
                        SPL_Price = 0,
                        SPL_State = VenuePriceStateEnum.CanNotChoice,
                        SPL_TimeSlotEnd = item.TimeSlotEnd,
                        CreateTime = DateTimeOffset.Now,
                    };
                    if (sitePrice != null)
                    {
                        priceDto.ID = sitePrice.ID;
                        priceDto.SPL_Price = sitePrice.SPL_Price;
                        priceDto.SPL_State = sitePrice.SPL_State;
                        priceDto.CreateTime = sitePrice.CreateTime;
                    }

                    priceSimple.SitePriceList.Add(priceDto);
                }
            }

            return result;
        }
    }
}
